<?php 
class User_model_user extends Model {
    private $table_user = 'user';
    private $table_group = 'group';
    private $table_role = 'role';
    private $table_position = 'position';
    private $table_user_position = 'user_position';
    
    
    public function add($username = '', $password = '', $email = '', $group = '', $role = '') {
        $username = trim($username);
        $password = trim($password);
        $email = trim($email);
        $group = trim($group);
        $role = trim($role);
        
        if (empty($username) || empty($password) || empty($email)) {
            tos_die('username or password cannot be none');
        }
        
        if ($this->user_exists($username, $email)) {
            tos_die('username or email address already exists');
        }
        
        $created = time();
        $changed = $created;
        
        $this->db->trans_start();
        $user_id = $this->db->insert(
            $this->table_user,
            array(
                'username'  => $username,
                'passcode'  => $this->_generate_passcode($password, $created),
                'email'     => $email,
                'created'   => $created,
                'changed'   => $changed
            )
        );
        
        if (0 >= (int)$user_id) {
            $this->db->trans_rollback();
            tos_die('create new user failed');
        }
        
        if ( ! empty($group)) {
            if ( ! $this->add_user_position($user_id, $group, $role)) {
                $this->db->trans_rollback();
                tos_die('add user position failed');
            }
        }
        
        $this->db->trans_commit();
        return $user_id;
    }
    
    
    public function user_exists($username, $email) {
        $sql = "SELECT `id` FROM `{$this->table_user}` WHERE `username`='{$username}' OR `email`='{$email}' LIMIT 1";
        $row = $this->db->row($sql);
        if ($row) {
            return (int) $row['id'];
        } else {
            return 0;
        }
        /*$row = $this->db->select_row(
            $this->table_user,
            array('id'),
            array(
                'username'  => $username
            )
        );
        if ($row) {
            return (int) $row['id'];
        } else {
            return 0;
        }*/
    }
    
    
    public function add_user_position($user_id = 0, $groupname = '', $rolename = '') {
        $user_id = (int) $user_id;
        if ($user_id <= 0) {
            tos_die('add_user_position user_id cannot be less then 0!');
        }
        $groupname = trim($groupname);
        if (empty($groupname)) {
            tos_die('add_user_position grouname cannot be empty');
        }
        $position_id = $this->add_position($groupname, $rolename);
        return $this->db->insert(
            $this->table_user_position,
            array(
                'user_id'       => $user_id,
                'position_id'   => $position_id
            ),
            array(
                'user_id'       => DB_DATA_INT,
                'position_id'   => DB_DATA_INT
            )
        );
    }
    
    
    public function add_position($groupname = '', $rolename = '') {
        $group_id = $this->add_group($groupname);
        
        if ($group_id <= 0) {
            tos_die('add group failed');
        }
        
        $rolename = trim($rolename);
        $role_id = 0;
        if ( ! empty($rolename)) {
            $role_id = $this->add_role($rolename);
            if ($role_id <= 0) {
                tos_die('add role failed');
            }
        }
        
        if ($position_id = $this->_add_position($group_id, $role_id)) {
            return $position_id;
        } else {
            tos_die('add position failed');
        }
    }
    
    
    public function add_group($name, $description = '') {
        $name = trim($name);
        if (empty($name)) {
            return 0;
        }
        $group_id = $this->group_exists($name);
        if ($group_id <= 0) {
            $description = trim($description);
            $group_id = $this->db->insert(
                $this->table_group,
                array(
                    'name'          => $name,
                    'description'   => $description
                )
            );
            if ($group_id <= 0) {
                tos_die('add group failed');
            }
        }
        return $group_id;
    }
    
    
    public function group_exists($name) {
        $row = $this->db->select_row(
            $this->table_group,
            array('id'),
            array(
                'name'  => $name
            )
        );
        if ($row) {
            return (int) $row['id'];
        } else {
            return 0;
        }
    }
    
    
    public function add_role($name, $description = '') {
        $name = trim($name);
        if (empty($name)) {
            return 0;
        }
        $role_id = $this->role_exists($name);
        if ($role_id <= 0) {
            $description = trim($description);
            $role_id = $this->db->insert(
                $this->table_role,
                array(
                    'name'          => $name,
                    'description'   => $description
                )
            );
            if ($role_id <= 0) {
                tos_die('add role failed');
            }
        }
        return $role_id;
    }
    
    
    public function role_exists($name) {
        $row = $this->db->select_row(
            $this->table_role,
            array('id'),
            array(
                'name'  => $name
            )
        );
        if ($row) {
            return (int) $row['id'];
        } else {
            return 0;
        }
    }
    
    
    public function authenticate($username, $password) {
        $username = trim($username);
        $password = trim($password);
        $row = $this->db->select_row(
            $this->table_user,
            array('id', 'passcode', 'created'),
            array('username' => $username)
        );
        
        if($row && $row['passcode'] == $this->_generate_passcode($password, $row['created'])) {
            return $row['id'];
        }
        return false;
    }
    
    
    
    private function _position_exists($group_id, $role_id) {
        $row = $this->db->select_row(
            $this->table_position,
            array('id'),
            array(
                'group_id'  => $group_id,
                'role_id'   => $role_id,
            ),
            array(
                'group_id'  => DB_DATA_INT,
                'role_id'   => DB_DATA_INT
            )
        );
        if ($row) {
            return (int) $row['id'];
        } else {
            return 0;
        }
    }
    
    
    private function _add_position($group_id, $role_id) {
        $group_id = (int) $group_id;
        $role_id = (int) $role_id;
        if ($group_id <= 0) {
            tos_die('_add_position group_id cannot be less then 1');
        }
        $position_id = $this->_position_exists($group_id, $role_id);
        if ($position_id <= 0) {
            $position_id = $this->db->insert(
                $this->table_position,
                array(
                    'group_id'  => $group_id,
                    'role_id'   => $role_id
                ),
                array(
                    'group_id'  => DB_DATA_INT,
                    'role_id'   => DB_DATA_INT
                )
            );
            if ($position_id <= 0) {
                tos_die('_add_position failed');
            }
        }
        
        return $position_id;
    }
    
    
    private function _generate_passcode($password, $created) {
        return '#$' . hash('sha256', $password. $this->_generate_salt($created));
    }
    
    
    private function _generate_salt($created) {
        $created = (string) $created;
        return substr(md5($created), 0, 16);
    }
    
}
?>